package controladorjuegolp2;

import com.thoughtworks.xstream.XStream;
import vistaDibujable.*;
import modeloEnum.tipoConst;
import modeloEntidades.*;

import modeloConstrucciones.*;
import modeloUnidadesMilitares.*;
import java.io.*;
import java.util.*;


public class pCivilizationG 
{   Jugador juegoRec;
    Mapa mapJuego;
    
    public pCivilizationG() throws IOException{
//        Scanner lectura=new Scanner(System.in);
//            System.out.println("Ingrese nombre del jugador");
//            String nombre= lectura.next();
//            this.juegoRec = new Jugador(nombre);
     //   this.mapJuego=new Mapa(20,20,"mapa1.txt");
    }
    
    //aceptarConstruir(x, y,tipoTerreno.arena, construccion); 
    public boolean aceptarConstruir(int x, int y, tipoTerreno tipo, Construccion construccion)
    {int cooX, cooY;
     int ocup, terr;
     
        cooX = construccion.getLargo();
        cooY = construccion.getAncho();

        for (int i=x; i<=x+cooX-1; i++)
         for (int j=y; j<=y+cooY-1; j++)
         {
            ocup = mapJuego.getCelda(i, j).ocupado();
            terr = mapJuego.buen_terreno(i, j, tipo);
            if (ocup==1 || terr==0) return false;
         }
        return true;
    }
    
    public boolean construyendo(Construccion construc, int op, int x, int y)
    {boolean guardo=false;
     int pob = 0, cost_fua = 0, mon = 0, mad = 0, cost_xp=0, petroleo=0;
     
     mon = construc.getPrecio();
     cost_fua = construc.getCosto_energia();
     cost_xp=construc.getXP();
        
     if (construc instanceof bungalowPequenho) {
        pob = ((bungalowPequenho)construc).getInc_poblacion();
        mad = ((bungalowPequenho)construc).getNum_recurso(); }
     if (construc instanceof casaPequenha) {
        pob = ((casaPequenha)construc).getInc_poblacion();
        mad = ((casaPequenha)construc).getNum_recurso(); }
     if (construc instanceof casaModerna) {
        pob = ((casaModerna)construc).getInc_poblacion();
        mad = ((casaModerna)construc).getNum_recurso(); }
     if (construc instanceof mansion) {
        pob = ((mansion)construc).getInc_poblacion();
        mad = ((mansion)construc).getNum_recurso(); }
     if (construc instanceof mansionPresidencial) pob = ((mansionPresidencial)construc).getBono_poblacion();
     if (construc instanceof tribunalFederal) pob = ((tribunalFederal)construc).getBono_poblacion();
     if (construc instanceof ayuntamiento) pob = ((ayuntamiento)construc).getBono_poblacion();
     if (construc instanceof cuartelMilitar) petroleo = ((cuartelMilitar)construc).getNum_recurso();
     if (construc instanceof fuerzasAereas) petroleo = ((fuerzasAereas)construc).getNum_recurso();
     if (construc instanceof baseNaval) petroleo = ((baseNaval)construc).getNum_recurso();
     if (construc instanceof graneroAlimenticio) mad = ((graneroAlimenticio)construc).getNumRecurso();
     if (construc instanceof pozoPetrolero) mad = ((pozoPetrolero)construc).getNumRecurso();
     if (construc instanceof aserradero) mad = ((aserradero)construc).getNumRecurso();
     if (construc instanceof minaMetales) mad = ((minaMetales)construc).getNumRecurso();

     if ((op>0 && op<=4) || (op>=11 && op<=14)) { //para casas e industria
         guardo = cambiaRecursosC(construc, x, y, pob, cost_fua, mon, mad, cost_xp); }
     if (op>=5 && op<=7) { //para gobierno
         guardo = cambiaRecursosGob(construc, x, y, pob, cost_fua, mon, cost_xp); }        
     if (op>=8 && op<=10) { //para edificios militares
         guardo = cambiaRecursosMil(construc, x, y, mon, cost_fua, cost_xp, petroleo); }   
     
     return guardo;
    }
    
    public boolean cambiaRecursosC(Construccion construc, int x, int y, int pob,int cost_fua,int mon,int mad, int cost_xp)
    { boolean guardo=false;
            if(((juegoRec.getJ_moneda()>mon) && (juegoRec.getJ_recursos().getJ_made()>mad) && (juegoRec.getJ_fua()>cost_fua) &&(juegoRec.getLim_pobl()> pob+juegoRec.getJ_pobl()) && (juegoRec.getJ_nivel()>=construc.getMin_nivel())))
            {
                guardarConstruccion(construc,x,y,construc.getID());
                juegoRec.setJ_pobl(juegoRec.getJ_pobl() + pob);
                juegoRec.setJ_moneda(juegoRec.getJ_moneda() - mon);
                juegoRec.getJ_recursos().setJ_made(juegoRec.getJ_recursos().getJ_made()-mad);
                juegoRec.setJ_fua((juegoRec.getJ_fua())-cost_fua);
                juegoRec.setJ_exper(juegoRec.getJ_exper()+cost_xp);
                juegoRec.getConstrucciones().add(construc);
                guardo=true;
            }
            return guardo;
    }
    
    public boolean cambiaRecursosGob(Construccion construc, int x, int y, int pob,int cost_fua,int mon, int cost_xp)
    { boolean guardo = false;
    
        if((juegoRec.getJ_moneda()>mon) && (juegoRec.getJ_fua()>cost_fua) && (juegoRec.getJ_nivel()>=construc.getMin_nivel()))
        {
            guardarConstruccion(construc,x,y,construc.getID());
            juegoRec.setLimPobl(juegoRec.getLim_pobl() + pob);
            juegoRec.setJ_moneda(juegoRec.getJ_moneda() - mon);
            juegoRec.setJ_fua((juegoRec.getJ_fua())- cost_fua);
            juegoRec.setJ_exper(juegoRec.getJ_exper()+cost_xp);
            juegoRec.getConstrucciones().add(construc);
            guardo=true;
        }
        return guardo;
    }
    
    public boolean cambiaRecursosMil(Construccion construc, int x, int y, int mon, int cost_fua, int cost_xp, int petroleo)
    {boolean guardo = false;
        if((juegoRec.getJ_moneda()>mon) && (juegoRec.getJ_fua()>cost_fua) &&(juegoRec.getJ_nivel()>=construc.getMin_nivel()))
        {
            guardarConstruccion(construc,x,y,construc.getID());
            juegoRec.setJ_moneda(juegoRec.getJ_moneda() - mon);
            juegoRec.getJ_recursos().setJ_petro(juegoRec.getJ_recursos().getJ_petro()-petroleo);
            juegoRec.setJ_fua((juegoRec.getJ_fua())- cost_fua);
            juegoRec.setJ_exper(juegoRec.getJ_exper()+cost_xp);
            juegoRec.getConstrucciones().add(construc);
            guardo = true;
        }
        return guardo;
    }
    
    public void construir(Mapa map,int x,int y)  throws IOException  {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Construccion construc=null;
        x--; y--;
        int opcion;
        boolean acepta = false, verif = false, def = false;
        Menu.construcciones();
        //Se solicita que tipo de construccion se quiere hacer
        System.out.println("(?) Que desea construir?");
        opcion = Integer.parseInt(br.readLine());
        String texto;
        switch(opcion)
        {
           case 1:   //esto es construir casas 
                construc = new bungalowPequenho(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break; //verifica tanto construcciones como terreno
           case 2:
                construc = new casaPequenha(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
          case 3:
                construc = new casaModerna(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 4:
                construc = new mansion(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 5:   //esto es construir gobiernos
                construc = new mansionPresidencial(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 6:
                construc = new tribunalFederal(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 7:
                construc = new ayuntamiento(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 8:   //esto es construir un edificio Militar
                construc = new cuartelMilitar(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 9:   
                construc = new fuerzasAereas(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 10:   
                construc = new baseNaval(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 11:  //esto es construir una industria
                construc = new graneroAlimenticio(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 12:
                construc = new pozoPetrolero(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 13:
                construc = new aserradero(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           case 14:
                construc = new minaMetales(x,y);
                acepta = aceptarConstruir(x, y,tipoTerreno.arena, construc); break;
           default:
               texto="Opcion Invalida, ingrese una opcion del menu correcta";
               Menu.error(texto);
               def = true; break;
       } 
       
        if (acepta && !def) verif = construyendo(construc, opcion, x, y);
        
        if ((!verif || !acepta) && !def)
        {
            if (!acepta) texto = "No se puede construir, revise el terreno y escoja otras coordenadas";
            else texto = "No cuenta con los suficientes recursos y o energia";
            construc = null;
            Menu.error(texto);
        }
    }
    
    public boolean validaTipoConst(int o, tipoConst constr)
    { 
        boolean pasoConstr=true; String texto="";
    
        switch (o)
        {
                case 1: //soldado
                        if (constr!=tipoConst.cuartelMilitar) {
                            texto = " (!) No puede crear un soldado, esta edificacion no es un cuartel ";
                            pasoConstr = false; }
                        break;
                case 2: //tanque simple
                        if (constr!=tipoConst.cuartelMilitar) {
                            texto = " (!) No puede crear un tanque simple, esta edificacion no es un cuartel ";
                            pasoConstr = false; }
                        break;
                case 3: //avion simple
                        if (constr!=tipoConst.fuerzasAereas) {
                            texto = " (!) No puede crear un avion simple, esta edificacion no son las fuerzas aereas ";
                            pasoConstr = false; }
                        break;
                case 4: //barco guerra
                        if (constr!=tipoConst.baseNaval) {
                            texto=" (!) No puede crear un barco de guerra, esta edificacion no es una base naval ";
                            pasoConstr = false; }
                        break;
                case 5: //fresas
                        if (constr!=tipoConst.graneroAlimenticio) {
                            texto=" (!) No puede cultivar fresas, esta edificacion no es un granero ";
                            pasoConstr = false; }
                        break;
                case 6: //leños
                        if (constr!=tipoConst.aserradero) {
                            texto=" (!) No puede talar, esta edificacion no es un aserradero ";
                            pasoConstr = false; }
                        break;
                case 7: //metales
                        if (constr!=tipoConst.minaMetales) {
                            texto=" (!) No puede extraer metales, esta edificacion no es una mina ";
                            pasoConstr = false; }
                        break;
                case 8: //petroleo
                        if (constr!=tipoConst.pozoPetrolero) {
                            texto=" (!) No puede explotar el pozo, esta edificacion no es un pozo ";
                            pasoConstr = false; }
                        break;
                default:
                    texto = " (!) Debe escoger una unidad u objeto a crear de las mostradas en el menu";
                    pasoConstr = false;
                    break;
        }
        
        if (!pasoConstr) Menu.error(texto);
        return pasoConstr;
    }
    
    public void compraPersonas(int opcion, Unidad s, Construccion construccion)
    { 
        String texto="";
        s.setEstado(2); //estado de la unidad en creacion
        construccion.setMaximoturno(s.getTardaTurnos());
        construccion.setNum_turno(construccion.getMaximoturno());
        juegoRec.getUnidades().add(s);  //introduzco la unidad al arreglo de unidades
        texto="La unidad "+s.getNombre()+" se empezo a crear correctamente\n";
        Menu.mensaje(texto);
    }
    
    public void compraProducto(int opcion, Construccion construccion){
        String texto="";
        
        if ( opcion == 5 ) {
            construccion.setMaximoturno(3);
            construccion.setNum_turno(construccion.getMaximoturno());
            texto="El cultivo de fresas se empezo a crear correctamente";
        }
        if ( opcion == 6 ) {
            construccion.setMaximoturno(4);
            construccion.setNum_turno(construccion.getMaximoturno());
            texto="Los lenios se empezaron a talar correctamente";
        }
        if ( opcion == 7 ) {
            construccion.setMaximoturno(3);
            construccion.setNum_turno(construccion.getMaximoturno());
            texto="Los minerales se empezaron a extraer correctamente";
        }
        if ( opcion == 8 ) {
            construccion.setMaximoturno(4);
            construccion.setNum_turno(construccion.getMaximoturno());
            texto="El pozo se empezo a explotar correctamente";
        }
        Menu.mensaje(texto);
    }
    
    public void compraUnidad(int opcion, Construccion construccion, int costoUnidad, Unidad s)
    {
        String texto="";
        int monJuego = juegoRec.getJ_moneda();
        
        if (monJuego >= costoUnidad) //el dinero alcanza
        {
            juegoRec.setJ_moneda(monJuego - costoUnidad); //actualizo la cantidad de monedas del jugador
            construccion.setestado(1); //estado del edificio: trabajando
            if ((opcion == 1 || opcion == 2 || opcion == 3 || opcion == 4)) compraPersonas(opcion, s, construccion);
            else if (opcion>=5 && opcion<=8) compraProducto(opcion, construccion);
        } 
        else //el dinero no alcanza =(
        { 
            texto=" (!) No tiene recursos suficientes para crear esta unidad ";
            Menu.error(texto);

            if (opcion == 1 || opcion == 2 || opcion == 3 || opcion == 4 )
            {
                s.setEstado(4); //eliminado
                s=null; //desreferencio la unidad 
            }
        }
    }
    
    public void crear(int x,int y)
    {
         Scanner lector = new Scanner(System.in);
         x--; y--;
         int opcion, costoUnidad = 0, monJuego;
         Unidad s = null;
         boolean pasoConstr=true; String texto="";

         //Se solicita que tipo de creacion se quiere hacer
         if (mapJuego.getCelda(x, y).sacaConstruccion()!=null)
         {
            Construccion construccion = mapJuego.getCelda(x, y).sacaConstruccion();
            tipoConst constr=construccion.getTipoC();
            
            Menu.objetos();
            opcion = lector.nextInt();

            pasoConstr = validaTipoConst(opcion, constr);
            if (pasoConstr && construccion.getestado()!=3)
            {
                texto=" (!) La construccion "+ construccion.getNombre()+ " no esta disponible para una nueva creacion\n";
                Menu.mensaje(texto);
            }
            if (pasoConstr && construccion.getestado()==3)
            {
                //creo una unidad
                switch (opcion) {
                     case 1:
                        s=((cuartelMilitar)construccion).producirSoldado(x,y);
                        costoUnidad = s.getCosto_unidad(); break;
                     case 2:
                        s=((cuartelMilitar)construccion).producirTanqueSimple(x, y);
                        costoUnidad = s.getCosto_unidad(); break;
                     case 3:
                        s=((fuerzasAereas)construccion).producirAvionSimple(x, y);
                        costoUnidad = s.getCosto_unidad(); break;
                     case 4:
                        s=((baseNaval)construccion).producirBarcoGuerra(x, y);
                        costoUnidad = s.getCosto_unidad(); break;
                     case 5:
                         costoUnidad = 30; break;
                     case 6:
                         costoUnidad = 40; break;
                     case 7:
                         costoUnidad = 25; break;
                     case 8:
                         costoUnidad = 35; break;
                     default: break;
                 }
                 compraUnidad(opcion, construccion, costoUnidad, s);
             }
         }
         else
         {
             texto = " (!) No hay ninguna construcción en esas coordenadas";
             Menu.mensaje(texto);
         }
    }
    

    public void recolectar (int x,int y){
        x--; y--; //no quites esta linea
       //Analizo Construccion en el parametro x e y
        
        Construccion Construct=this.mapJuego.getCelda(x, y).sacaConstruccion();
        //obteng la contruccion en la coordenada buscada
        if (Construct!=null){
              switch (Construct.getestado()){  //en q estado me encuentro
                  case 1: 
                          System.out.printf("(!) Esta trabajando - no molestar ");//estoy trabajando
                          break;
                  case 2:       
                          //obtenemos los recursos o unidades que la contruccion produce
                          obtenerRecursos(Construct,x,y);
                          break;
                   case 3:
                          System.out.printf("No hay ningun objeto creandose ni esperando a ser recolectado\n");//esta libre para usar el comando crear
                          break;
                   default:
                          break;
            }//Fin del switch
        }
       else System.out.printf("(!) No hay construccion en las coordenadas %d,%d",y+1,x+1);
   }

    public void verificarContratos(Construccion auxcons)
    { 
        //AGREGADO LAB3
        //verifica si debe pagarle a los amigos contratados (ya sea que el edificio este con todos sus contratados completos o no)
        if (auxcons instanceof Gobierno)
        {
            for (int j=0;j<((Gobierno)auxcons).getAmigosContratados().size();j++)
            {
                Amigo amigo;
                amigo = ((Gobierno)auxcons).getAmigosContratados().get(j);
                if (juegoRec.getTurnoJ()%amigo.getTurnosPago()==0)
                {
                    //llega el momento de verificar si se le puede pagar
                    if (amigo.getPago()>juegoRec.getJ_moneda())
                    {
                        Menu.mensaje("No alcanza el dinero para mantener a su amigo "+amigo.getNombre()+ " como contratado en el edificio "+auxcons.getNombre()+" :(\n");
                        //en el caso de que el jugador no tenga dinero para mantenerlo como contratado
                        if(auxcons.getestado()==2)
                        {
                            obtenerRecursos(auxcons, auxcons.getPos_x(),auxcons.getPos_y());
                        }
                        ((Gobierno)auxcons).removerAmigo(j);
                        ((Gobierno)auxcons).setestado(3); //zzz, o sea ya no se me pagarán cada N turnos
                    }
                    else
                    {
                        //se le paga
                        juegoRec.setJ_moneda(juegoRec.getJ_moneda()-amigo.getPago());
                    }
                }
            }
        }
    }
    
    public void actualizaturnos(Mapa map)
    {
        int i, Numturno;
        Construccion auxcons=null;
        juegoRec.setTurnoJ(juegoRec.getTurnoJ()+1);

        if (juegoRec.getLim_fua()>juegoRec.getJ_fua()) juegoRec.setJ_fua(juegoRec.getJ_fua()+1);
        if (juegoRec.getLim_exper()==juegoRec.getJ_exper()) juegoRec.actualiza_lim_exper();
        
        for (i=0;i<juegoRec.getConstrucciones().size();i++)
        {
            auxcons = juegoRec.getConstrucciones().get(i);
            Numturno = auxcons.getNum_turno();
            if (Numturno > 0 && auxcons.getestado()==1) {
                auxcons.setNum_turno(Numturno-1);
            } //estado 1 = construccion trabajando
            if (auxcons.getNum_turno()==0){//si turno es igual a 0 signifca q ya esta listo
               auxcons.setNum_turno(1);
               auxcons.setestado(2); //seteo el estado de construcciones a 2 q significa q tmb esta listo para recolectar
               mod_char_varios(auxcons, auxcons.getPos_x(), auxcons.getPos_y(), '!'); //ya se puede recolectar ;)
            }
            verificarContratos(auxcons);
        }
        ///////////////////////
        System.out.println("Numero de turno de juego:" +juegoRec.getTurnoJ());
    }
    
    ///modificacion segundo lab, comando para agregar amigos al juego
     private void mostrarAmigos()
    {
           
          System.out.println("!!!!!!!!!!!!!!!!!!!NUESTROS AMIGOS!!!!!!!!!!!!!!!!");
          for(int i=0;i<juegoRec.getAmigos().size();i++)
          {
                     System.out.println("("+(i+1)+") Nombre:  " +juegoRec.getAmigos().get(i).getNombre() + "\t\t" +"Nivel:  " +juegoRec.getAmigos().get(i).getNivel());
          }
          System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");        
         
    }
    
    private int agregarAmigo(BufferedReader br ) throws IOException
    {               
        System.out.println("Ingrese el nombre del amigo que desea agregar");

        Scanner sc = new Scanner(System.in);
        String nombre = sc.next();
        System.out.println("Ingrese el nivel de su amigo");
        int nivel = Integer.parseInt(br.readLine());

     //   Amigo nuevoAmigo=new Amigo(nombre,nivel);

        for (int i=0;i<juegoRec.getAmigos().size();i++)
        {
            if (juegoRec.getAmigos().get(i).getNombre().equals(nombre))
            {
                System.out.println("El amigo ya existe, por favor elija otro amigo");
                return 0;
            }

        }
        Amigo nuevoAmigo=new Amigo(nombre,nivel,1);
        nuevoAmigo.cargarUnidadesAmigos();
        juegoRec.getAmigos().add(nuevoAmigo);
        /////////Ahora si funciona, nuestro amigo es instanciado con unas unidades fijas!!!! :)
        System.out.println("nuestro amigo ha sido agregado");
        System.out.println("!!!!!!!!!!!!!!!SUS UNIDADES!!!!!!!!!!!!!!");
        for (int i=0;i<nuevoAmigo.getUnidadesAmigos().size();i++)
         System.out.println("Esto es el ID de la unidad: -->" + nuevoAmigo.getUnidadesAmigos().get(i).getID());

        return 1;
    }


    private void contratar(Mapa map,int x, int y)
    {
        Gobierno auxiliarGob=obtenerGobierno(map,x,y);
 
        if (auxiliarGob!=null)
        {
            mostrarAmigos();
            System.out.println("Ingrese el nombre de su amigo a contratar");
            Scanner sc = new Scanner(System.in);
            String nombre = sc.next();
          
            Amigo auxiliarAmigo=obtenerAmigo(nombre);
           
            if (auxiliarAmigo!=null)
            {
               //if((juegoRec.getJ_moneda()>=auxiliarGob.getPrecioContrato())&&(!auxiliarGob.esAmigo(nombre))&&(auxiliarGob.getAmigosContratados().size()<auxiliarGob.getNumMaxContratado()))
               if((juegoRec.getJ_moneda()>=auxiliarAmigo.getPago())&&(!auxiliarGob.esAmigo(nombre))&&(auxiliarGob.getAmigosContratados().size()<auxiliarGob.getNumMaxContratado())) 
               {
                   auxiliarGob.contratarAmigo(auxiliarAmigo);
                   juegoRec.setJ_moneda(juegoRec.getJ_moneda() - auxiliarAmigo.getPago());
                   
                   System.out.println("usted contrato a su amigo:"+nombre);
                   System.out.println("necesitas: "+(auxiliarGob.getNumMaxContratado())+" Tienes actualmente " +(auxiliarGob.getAmigosContratados().size()));
                   if(auxiliarGob.getNumMaxContratado()==auxiliarGob.getAmigosContratados().size())
                   {
                       juegoRec.setJ_moneda(juegoRec.getJ_moneda()+auxiliarGob.getBonificacion());
                       auxiliarGob.setestado(1);
                       auxiliarGob.setPagarle(1); //a partir de ahora se pagara a sus contratados porque ya los completo
                   }
               }
               else  
                System.out.println("No se puede contratar a este amigo, revise parametros del juego");  
            }
            else
                System.out.println("El amigo no existe dentro del juego");
            
        }
        else
        {
                System.out.println("La posicion no hace referencia a un Gobierno, redefinir parametros x e y");
                System.out.println();
        }   
    }
    
    private Gobierno obtenerGobierno(Mapa map,int x, int y) {
        System.out.println();  
        
        Construccion Construct=map.getCelda(x, y).sacaConstruccion();
        if(Construct instanceof Gobierno) return (Gobierno)(Construct);
        return null;
    }

    private Amigo obtenerAmigo(String nombre) 
    {
        System.out.println();        
        for(int i=0;i<juegoRec.getAmigos().size();i++)
        {
            if (juegoRec.getAmigos().get(i).getNombre().equals(nombre)) return juegoRec.getAmigos().get(i);
        }
        return null;
    }
    
     private void mostrarListaUnidades()
    {
         System.out.println("!!!!!!!!!!!!!!!!!!!NUESTRAS UNIDADES DE DEFENSA!!!!!!!!!!!!!!!!!");
          for(int i=0;i<juegoRec.getUnidades().size();i++)
          {
                     System.out.println("("+(i+1)+") Nombre:  " +juegoRec.getUnidades().get(i).getNombre() + "\t\t" +"Resistencia:  " +juegoRec.getUnidades().get(i).getResistencia());
          }
       
    }
    
    private void seleccionUnidades()
    {
           Scanner sc= new Scanner(System.in);
           int anhadidos=0;
           while(anhadidos<3)
           {
                mostrarListaUnidades();
                System.out.println("(?) Ingrese el numero de su unidad: ");
                int Unidad=sc.nextInt();
                if((Unidad>0)&&(Unidad<=juegoRec.getUnidades().size()))
                {
                    juegoRec.getUnidadesBatalla().add(juegoRec.getUnidades().get(Unidad-1));
                    anhadidos++;
                }
                else
                System.out.println("Revise la lista e Ingrese una opcion correcta");
           }
                
    }
    
    public Unidad elegirunidad(){
        System.out.println();
        System.out.println("Elija el numero de la unidad que atacara:  ");
        Scanner sc= new Scanner(System.in);
        int indice=sc.nextInt();
        
        return juegoRec.getUnidadesBatalla().get(indice-1);
    }

    public Unidad elegircontraquien(ArrayList<Unidad> enemigos ){
        System.out.println("Elija el numero de la unidad que sera atacada:  ");
        Scanner sc= new Scanner(System.in);
        int indice=sc.nextInt();
        return enemigos.get(indice-1);
    }
    
    public void actualizaunidades(Unidad atacante, Unidad atacado){

        int nuevavida;
        if (atacante.getBonusataque()==atacado.getTipounidad())
            nuevavida=atacado.getVida()-atacante.getAtaque()*2;
        else
            nuevavida=atacado.getVida()-atacante.getAtaque();
            atacado.setVida(nuevavida);
        if (atacado.getVida()<=0) {
            atacado.setEstado(4);
            if (atacado.getVida()<0) atacado.setVida(0);
        }
        juegoRec.setJ_fua(juegoRec.getJ_fua()-1);
        juegoRec.setJ_exper(juegoRec.getJ_fua()+1);
    }

    public int condicionesdepelea(Amigo amigo)
    {
        ArrayList<Unidad> tropas=juegoRec.getUnidadesBatalla();
        boolean perdimos=true,ganamos=true;
        for (Unidad nuestraunidad:tropas){
                if (nuestraunidad.getEstado()!=4)
                {
                    perdimos=false;
                    break;
                }

        }
        ArrayList<Unidad> tropasenemigas = amigo.getUnidadesAmigos();
        for (Unidad enemigaunidad:tropasenemigas){
                if(enemigaunidad.getEstado()!=4)
                {
                    ganamos=false;
                    break;
                }
        }
        if (perdimos) return 3;
        else if (ganamos) return 1;
             else  return 2;

    }

    public void mostrarbatalla(Amigo amigo){
        System.out.println();
        System.out.println("                      UNIDADES AMIGAS                         ");
        ArrayList<Unidad> unidadesbatalla=juegoRec.getUnidadesBatalla();
        String n="Nombre",v="Vida",b="Bonus contra";
        
        
        int i=1;
            System.out.printf("%-23s %-20s %-20s\n", n,v,b);
           for (Unidad nuestrasunidades:unidadesbatalla){
                
                System.out.print(i+ "° ");
                nuestrasunidades.imprimiratributos();
                i++;
            }
            System.out.println("                      UNIDADES ENEMIGAS                       ");

            ArrayList<Unidad> enemigos=amigo.getUnidadesAmigos();
            i=1;
            System.out.printf("%-23s %-20s %-20s\n", n,v,b);
            for (Unidad unidadesenemigas:enemigos)
            {
                
                System.out.print(i+ "° ");
                unidadesenemigas.imprimiratributos();
                i++;
            }

    }

    public void atacaelenemigo(Amigo amigo)
    {
        int i=0;
        Unidad atacante=null;
        Unidad atacado=null;
        System.out.println();
        System.out.println("-> El enemigo esta furioso y nos ha atacado :( ");
        System.out.println("-> Nos ha ocasionado danioZZZZZZZ =S");
        System.out.println();            
            
            for(i=0;i<amigo.getUnidadesAmigos().size();i++)
                if (amigo.getUnidadesAmigos().get(i).getEstado()!=4) atacante=amigo.getUnidadesAmigos().get(i);            
            
            for(i=0;i<juegoRec.getUnidadesBatalla().size();i++)
                if (juegoRec.getUnidadesBatalla().get(i).getEstado()!=4) atacado=juegoRec.getUnidadesBatalla().get(i);

        actualizaunidades(atacante,atacado);
    }

    public void devolvervida(){
        ArrayList<Unidad> aux=juegoRec.getUnidadesBatalla();
        for (Unidad unidad:aux){
            if (unidad.getEstado()==4) unidad.setVida(unidad.getResistencia());
        }
    }

    public void cargarganancias()
    {
        juegoRec.setJ_moneda(juegoRec.getJ_moneda()+500);
        juegoRec.setJ_exper(juegoRec.getJ_exper()+30);
    }

    public void batalla(Amigo amigo){
       int resultado; // 1 gane, 2 siguen peleando, 3 perdi

       System.out.println("//////////////////////////////////////////////////////////////");
       System.out.println("//                       BATALLA                            //");
       System.out.println("//////////////////////////////////////////////////////////////");
       System.out.println("-> Estamos con " + juegoRec.getJ_fua()+" de fuaaaaaaa");
       mostrarbatalla(amigo);

       while (true){
           
            Unidad atacante=elegirunidad();
            Unidad atacado=elegircontraquien(amigo.getUnidadesAmigos());

            actualizaunidades(atacante,atacado);
            resultado=condicionesdepelea(amigo);
            System.out.println();
            System.out.println("-> Despues de nuestro super ataque ");
            System.out.println("-> estamos con " + juegoRec.getJ_fua()+" de fuaaaaaaa");
            System.out.println();
            
            mostrarbatalla(amigo);

            if (resultado==3) {
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println("//                                                          //");
                System.out.println("//    Resultado: SE TERMINO LA BATALLA, PERDIMOS :(         //");
                System.out.println("//                                                          //");
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println();
                return;
            }
            else if (resultado==1){
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println("//                                                          //");
                System.out.println("//    Resultado: SE TERMINO LA BATALLA , GANAMOS ;) !       //");
                System.out.println("//                                                          //");
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println();
                devolvervida();
                cargarganancias();
                return;
           }
            atacaelenemigo(amigo);
            
            resultado=condicionesdepelea(amigo);
            System.out.println ("-> Estamos con " + juegoRec.getJ_fua()+" de fuaaaaaaa");
            mostrarbatalla(amigo);

            if (resultado==3) {
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println("//                                                          //");
                System.out.println("//    Resultado: SE TERMINO LA BATALLA, PERDIMOS :(         //");
                System.out.println("//                                                          //");
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println();
                return;
            }
            else if (resultado==1){
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println("//                                                          //");
                System.out.println("//    Resultado: SE TERMINO LA BATALLA , GANAMOS ;) !       //");
                System.out.println("//                                                          //");
                System.out.println("//////////////////////////////////////////////////////////////");
                System.out.println();
                devolvervida();
                cargarganancias();
                return;
            }
      }
    }

    public void invadir(Amigo amigoInvadido)
    {
        //implementemos un primer caso ideal
        if (amigoInvadido.getResultadoUltimaBatalla()==1)
        { 
            ArrayList<Unidad> aux = new ArrayList<Unidad>();
            juegoRec.setUnidadesBatalla(aux);
            seleccionUnidades();
            batalla(amigoInvadido);
        }
        else
        {
            //si mi amigo tiene una batalla perdida ==0
            amigoInvadido.cargarUnidadesAmigos(); //todas sus unidades vuelven a ser instanciadas con vida maxima
        }
    }

    public void guardarUnidad(Unidad personaje, int x, int y,char id)
    {
        int cooX = personaje.getLargo();
        int cooY = personaje.getAncho();

        for (int i=x; i<=x+cooX-1; i++)
         for (int j=y; j<=y+cooY-1; j++)
         {
            this.mapJuego.getCelda(i, j).mod_ocupa_personaje(personaje); //modifica la variable personaje de la celda
            this.mapJuego.getCelda(i, j).mod_char(id);
            this.mapJuego.getCelda(i, j).referenciarUni(personaje); //modifica la variable "objeto" de la celda
         }
     }

   public void guardarConstruccion(Construccion construc, int x, int y,char id)
    {
        int cooX = construc.getLargo();
        int cooY = construc.getAncho();

        for (int i=x; i<=x+cooX-1; i++)
         for (int j=y; j<=y+cooY-1; j++)
         {
            this.mapJuego.getCelda(i, j).mod_ocupa_const(construc); //modifica la variable construccion de la celda
            this.mapJuego.getCelda(i, j).mod_char(id);
            this.mapJuego.getCelda(i, j).referenciarConst(construc); //modifica la variable "objeto" de la celda
         }
     }
   
     public void mod_char_varios(Construccion construccion, int x, int y, char id){
        int cooX = construccion.getLargo();
        int cooY = construccion.getAncho();

        for (int i=x; i<=x+cooX-1; i++)
         for (int j=y; j<=y+cooY-1; j++)
         {
            this.mapJuego.getCelda(i, j).mod_char(id);
         }
     }
     
     public int creaUniOk(Unidad uni, int tipo, int x, int y)
     {
       int cooX = uni.getAncho();
       int cooY = uni.getLargo();

       for (int i=x; i<=cooX+x-1; i++)
           for (int j=y; j<=cooY+y-1; j++)
           {
               if ((mapJuego.getCelda(j,i).lee_char()=='~' && tipo == 2) ||(mapJuego.getCelda(j, i).lee_char()=='*' && tipo==1) || (mapJuego.getCelda(j,i).lee_char()!='~' && mapJuego.getCelda(j,i).lee_char()!='*'))
               {
                   return 0;
               }
           }
       return 1;
    }

    private void obtenerRecursos(Construccion Construc,int x, int y) {
         //termine de trabajar ya lo cree(se viazualiza en el mapa)
         //El recolectar se separa x Viviendas,Industrias, Unidades y Gobierno(cada uno genera algo diferente)
         Scanner lector = new Scanner(System.in);
         int entero, tipo=0;
        
        if ((Construc instanceof Militar)==true)
        {
            Unidad auxunidad=null;
            char id;
            int entero1, entero2;

            for (int i=0;i<this.juegoRec.getUnidades().size();i++)
            {
                 auxunidad=this.juegoRec.getUnidades().get(i);
                 if (auxunidad.getX()==x && auxunidad.getY()== y)break;
            }

            //trabajo con el arraylist de mis unidades
            id = auxunidad.getID();
            auxunidad.setEstado(2); //seteo el estado de unidades a unidad lista(2) (o sea terminado de construir)

            System.out.println("(?) Desea colocar su unidad en el mapa? Si=1 No=0");
            entero = lector.nextInt();

            if(entero==1)
            {
                while (true){
                    System.out.println("(?) En que posicion x, y desea ubicarlo?");
                    entero1 = lector.nextInt(); entero1--;
                    entero2 = lector.nextInt(); entero2--;
                    if (this.mapJuego.getCelda(entero1, entero2).sacaConstruccion()==null &&
                        this.mapJuego.getCelda(entero1, entero2).sacaUnidad()== null
                        ){
                            if (auxunidad instanceof barcoGuerra)
                            {
                                tipo = 1;
                            }
                            else tipo = 2;
                            if (creaUniOk(auxunidad, tipo, entero1, entero2)==1)
                            {
                                 Construc.setestado(3); //cambio el estado de la construccion a libre (3)
                                 auxunidad.setEstado(3); //cambio el estado de "unidad en el mapa" (3)
                                 guardarUnidad(auxunidad, entero2, entero1, id);
                                 auxunidad.setX(entero2);
                                 auxunidad.setY(entero1);
                                 break;
                            }
                            else System.out.println("(!) Posicion no valida");
                    }
                    else System.out.println("(!) Posicion no valida");
                }
            }
      }
      else
      {
          if ((Construc instanceof Gobierno))
          {
              this.juegoRec.setJ_moneda(juegoRec.getJ_moneda()+((Gobierno)Construc).recolectarDinero());
              this.juegoRec.setJ_exper(juegoRec.getJ_exper()+((Gobierno)Construc).recolectarExp());
              this.juegoRec.setJ_fua(juegoRec.getJ_fua()-((Gobierno)Construc).obtenerGastoFua());
              Construc.setestado(1);
              Construc.setNum_turno(Construc.getMaximoturno());
          }

          if((Construc instanceof Vivienda))
          {
              this.juegoRec.setJ_moneda(juegoRec.getJ_moneda()+((Vivienda)Construc).recolectarDinero());
              this.juegoRec.setJ_exper(juegoRec.getJ_exper()+((Vivienda)Construc).recolectarExp());
              this.juegoRec.setJ_fua(juegoRec.getJ_fua()-((Vivienda)Construc).obtenerGastoFua());
              Construc.setestado(1);
              Construc.setNum_turno(Construc.getMaximoturno());
          }

          if (Construc instanceof Industria)
          {
               if ((Construc instanceof aserradero))
                   this.juegoRec.getJ_recursos().setJ_made(juegoRec.getJ_recursos().getJ_made()+((Industria)Construc).recolectarRecursos());
               if ((Construc instanceof pozoPetrolero))
                   this.juegoRec.getJ_recursos().setJ_petro(juegoRec.getJ_recursos().getJ_petro()+((Industria)Construc).recolectarRecursos());
               if ((Construc instanceof minaMetales))
                   this.juegoRec.getJ_recursos().setJ_minerales(juegoRec.getJ_recursos().getJ_minerales()+((Industria)Construc).recolectarRecursos());

               this.juegoRec.setJ_fua(juegoRec.getJ_fua()-((Industria)Construc).obtenerGastoFua());
               this.juegoRec.setJ_exper(juegoRec.getJ_exper()+((Industria)Construc).recolectarExp());
          }
      }
      mod_char_varios(Construc, Construc.getPos_x(), Construc.getPos_y(), Construc.getID());
    }

    public void generarXmlJuego(String nombre)
    {
        // TODO Auto-generated method stub
        XStream xs = new XStream();
        String temp = xs.toXML(this);
        try {
            FileWriter fw = new FileWriter(nombre+".xml");
            fw.write(temp);
            fw.close();
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }

    public void cargarXMLInicial(String nombre)
    {
        XStream xs = new XStream();
        try
        {
            FileReader fr1 = new FileReader(nombre+".xml");
            pCivilizationG aux=(pCivilizationG)xs.fromXML(fr1);
            this.juegoRec=aux.juegoRec;
            this.mapJuego=aux.mapJuego;
            fr1.close();
        }
        catch (Exception e){
            System.out.println(e.toString());
        }
    }
       
   private String formatInt(int x){
       String s = "" + x;
       if(s.length() < 2) return "0" + x;
       else return s;
   }
   private String generaNombre()
   {
       String dato;
           Calendar cal = Calendar.getInstance();
           int dia= cal.get(Calendar.DATE);
           int mes= cal.get(Calendar.MONTH)+1;
           int anho= cal.get(Calendar.YEAR);
           int hora = cal.get(Calendar.HOUR);
           int min = cal.get(Calendar.MINUTE);
           int seg = cal.get(Calendar.SECOND);
           dato = formatInt(dia) + formatInt(mes) + formatInt(anho) + formatInt(hora) + formatInt(min) + formatInt(seg);
           //dato= "07092011093845";
           //PrintStream ps = new PrintStream(new StringOutputStream());
           //System.out.println(dato);
       return dato;
   }

   private void guardarBinario(String name) throws IOException
   {
        ObjectOutputStream Escritor = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(name)));

        Escritor.writeObject(mapJuego);
        Escritor.writeObject(juegoRec);

        Escritor.close();
   }
   
    private void guardarJuego() throws IOException {
       Scanner opt=new Scanner(System.in);
        System.out.println("(?) Desea guardar Juego?  si - no");
        if (opt.next().equals("si"))
        {
           // System.out.println("Ingrese el nombre del archivo a guardar");
            String nombreArch= generaNombre();
            guardarBinario("peruCivilization"+nombreArch);
            // generarXmlJuego(opt.next());
        }
    }
    
   public void abrirArchBinario(String name) throws IOException, ClassNotFoundException
   {
       ObjectInputStream Lector = new ObjectInputStream(new BufferedInputStream(new FileInputStream(name)));
       while(true) 
       {
	  Mapa mapAuxiliar;
          Jugador jugadorAux;

		try { 
                        mapAuxiliar = (Mapa)Lector.readObject(); 
                        jugadorAux = (Jugador)Lector.readObject();
                    }
		catch(EOFException ex){ break; }
                mapJuego=mapAuxiliar;
                juegoRec=jugadorAux;
	
        }   
       Lector.close();
   }
   
   public void cargarDatosJuego() throws Exception
    {
        Scanner opt=new Scanner(System.in);
        System.out.println("Desea cargar Juego anterior?  si - no");
        if (opt.next().equals("si"))
        {
            System.out.println("Ingrese el nombre del archivo guardado");
            abrirArchBinario(opt.next());
            //cargarXMLInicial(opt.next());
        }
        else
        {
            Scanner lectura=new Scanner(System.in);
            System.out.println("Ingrese nombre del jugador");
            String nombre= lectura.next();
            this.juegoRec = new Jugador(nombre);     
            System.out.println("Ingrese nombre del mapa a usar (mapa o mapa1)");
            String nameArch=lectura.next();
            this.mapJuego=new Mapa(20,20,nameArch+".txt");            
        }
    }
   
    public void jugar() throws Exception
    {
        cargarDatosJuego();
        //cargarXMLInicial();
        Scanner lector = new Scanner(System.in);
  
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        //Crea el mapa
        boolean sal=false;//condicional para confirmacion de salida
        int res, y, x;
        
        while (true)
        {
            Menu.recursosJuego(juegoRec.getJ_nivel(), juegoRec.getJ_exper(), juegoRec.getJ_pobl(), juegoRec.getLim_pobl(), juegoRec.getJ_fua(), juegoRec.getJ_recursos().getJ_made(), juegoRec.getJ_recursos().getJ_petro(), juegoRec.getJ_recursos().getJ_minerales(),juegoRec.getJ_moneda(),juegoRec.getNombre()); //Muestra los valores de los recursos, energia, poblacion, etc. en todo momento del juego
            mapJuego.dibujar(20,20); //Muestra el mapa en pantalla
            Menu.acciones();
            int entero = -1;
            try{
                entero = lector.nextInt();
            }catch(Exception ex){
                System.out.println("pon numeritos, pe");
                String s = lector.next();
                continue;
            }
            switch(entero)
            {
                case 1: //construir
                    Menu.mensaje("Elija parametros X e Y");
                    y = lector.nextInt();
                    x = lector.nextInt();
                    construir(mapJuego,x,y); break;
                case 2://recolectar
                    Menu.mensaje("Elija parametros X e Y");
                    y = lector.nextInt();
                    x = lector.nextInt();
                    recolectar(x,y); break;                  
                case 3: //crea
                    Menu.mensaje("Elija parametros X e Y");
                    y = lector.nextInt();
                    x = lector.nextInt();
                    crear(x,y); break;
                case 4: //solo actualiza los turnos de las construcciones
                    actualizaturnos(mapJuego);
                    break; 
                case 5: //Amigo a agregar
                    mostrarAmigos();
                    agregarAmigo(br);
                    break;  
                case 6:   //Contratar amigo para construccion gobierno
                    Menu.mensaje("Ingrese la posicion x e y de su construccion tipo gobierno");
                    y = lector.nextInt();
                    x = lector.nextInt();
                    contratar(mapJuego,x-1,y-1);
                    break;
                case 7: //Invadir a un amigo
                   if (juegoRec.getUnidades().size()<3)
                   {
                       System.out.println("No cuenta con las unidades suficientes para invadir ):");
                       break;
                   }
                   mostrarAmigos();
                   System.out.println("Ingrese el numero del amigo al cual desea invadir");
                   int numAmigo=lector.nextInt();
                   if((numAmigo>0)&&(numAmigo<=juegoRec.getAmigos().size())) invadir(juegoRec.getAmigos().get(numAmigo-1));
                   else
                       System.out.println("Revise la lista e Ingrese una opcion correcta");     
                   break;    
                case 8: //Confirmacion si el usuario desea salir
                   System.out.println("(?) Esta seguro de que desea salir del juego? 1 = Si 0 = No");
                   int ent=0;
                
                   while(true){
                          try
                          {
                            ent = lector.nextInt();
                            if ((ent!=0)&&(ent!=1)) System.out.println("Ingrese un numero valido '1' - '0'");
                            if (ent==0) break;
                            if (ent==1) break;
                          }
                          catch(Exception e)
                          {   
                              System.out.println("Por favor ingrese un numero '1' - '0'");
                              lector.nextLine();
                              ent =lector.nextInt();
                              if ((ent!=0)&&(ent!=1)) System.out.println("Ingrese un numero valido '1' - '0'");
                          }
                          if (ent==0) break;
                          if (ent==1) break;
                    }
                     if(ent==1)
                     {
                        Ranking.Ranking.RegistrarPuntaje(juegoRec.getNombre(), juegoRec.getJ_exper());
                        sal=true;
                     }
                     else sal=false;
                default: break;
            }
            
            if (sal==true)
            {
                guardarJuego();
                //generarXml();
                break;
            }
                
        }
        
    }
}


